﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Reflection;

namespace Lilium.Web.Mvc
{
	/// <summary>
	/// 
	/// </summary>
	/// <remarks>
	/// Thread Safety
	/// This type is thread safe.
	/// </remarks>
	//TODO: добавить возможность работы с debug скриптами.
	public class EmbeededScriptResourceLibrary: ScriptResourceLibrary
	{
		public EmbeededScriptResourceLibrary(
			string name,
			Assembly resourceAssembly,
			string resourceNamespace,
			string contentType,
			OutputCachePolicy cachePolicy,
			IEnumerable<ScriptResource> resources)
			: base(name, resources)
		{
			if (resourceAssembly == null)
				throw new ArgumentNullException("resourceAssembly");
			if (cachePolicy == null)
				throw new ArgumentNullException("cachePolicy");

			m_CachePolicy = cachePolicy;
			m_ContentType = contentType;
			m_ResourceAssembly = resourceAssembly;
			m_ResourceNamespace = resourceNamespace;
		}

		protected override void OnGetScriptResource(GetScriptResourceEventArgs e)
		{
			if (e == null)
				throw new ArgumentNullException("e");

			base.OnGetScriptResource(e);
			if (e.ScriptResource == null)
				e.ScriptResource = GetEmbeededResource(e.ResourceName);
		}

		private ScriptResource GetEmbeededResource(string name)
		{
			EmbeededScriptResource resource;
			lock (ScriptResourceCache)
				if (!ScriptResourceCache.TryGetValue(name, out resource))
				{
					resource = new EmbeededScriptResource(
						name,
						ResourceAssembly,
						ResourceNamespace + "." + name,
						ContentType,
						CachePolicy);
					ScriptResourceCache[name] = resource;
				}
			return resource;
		}

		#region private OutputCachePolicy CachePolicy

		private readonly OutputCachePolicy m_CachePolicy;

		private OutputCachePolicy CachePolicy { [DebuggerNonUserCodeAttribute] get { return m_CachePolicy; } }

		#endregion

		#region private string ContentType

		private readonly string m_ContentType;

		private string ContentType { [DebuggerNonUserCodeAttribute] get { return m_ContentType; } }

		#endregion

		#region private Dictionary<string, EmbeededScriptResource> ScriptResourceCache

		private readonly Dictionary<string, EmbeededScriptResource> m_ScriptResourceCache = new Dictionary<string, EmbeededScriptResource>();

		private Dictionary<string, EmbeededScriptResource> ScriptResourceCache { [DebuggerNonUserCodeAttribute] get { return m_ScriptResourceCache; } }

		#endregion

		#region private Assembly ResourceAssembly

		private readonly Assembly m_ResourceAssembly;

		private Assembly ResourceAssembly { [DebuggerNonUserCodeAttribute] get { return m_ResourceAssembly; } }

		#endregion

		#region private string ResourceNamespace

		private readonly string m_ResourceNamespace;

		private string ResourceNamespace { [DebuggerNonUserCodeAttribute] get { return m_ResourceNamespace; } }

		#endregion
	}
}